package org.example.lethear.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.example.lethear.dto.common.PageResult;
import org.example.lethear.dto.whisper.WhisperCreateRequest;
import org.example.lethear.dto.whisper.WhisperDTO;
import org.example.lethear.dto.whisper.WhisperSettingsDTO;
import org.example.lethear.entity.User;
import org.example.lethear.entity.Whisper;
import org.example.lethear.entity.WhisperSettings;
import org.example.lethear.exception.BusinessException;
import org.example.lethear.exception.ResourceNotFoundException;
import org.example.lethear.repository.UserRepository;
import org.example.lethear.repository.WhisperRepository;
import org.example.lethear.repository.WhisperSettingsRepository;
import org.example.lethear.utils.Result;
import org.example.lethear.utils.SecurityUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 悄悄话管理控制器
 */
@Tag(name = "悄悄话管理", description = "悄悄话发送、接收、设置等相关接口")
@RestController
@RequestMapping("/whispers")
@RequiredArgsConstructor
public class WhisperController {
    
    private final WhisperRepository whisperRepository;
    private final WhisperSettingsRepository whisperSettingsRepository;
    private final UserRepository userRepository;
    
    /**
     * 发送悄悄话
     */
    @Operation(summary = "发送悄悄话", description = "发送悄悄话给指定用户或暗号")
    @PostMapping
    @Transactional
    public Result<WhisperDTO> sendWhisper(@Valid @RequestBody WhisperCreateRequest request) {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        
        // 创建悄悄话
        Whisper whisper = new Whisper();
        whisper.setTargetType("username".equals(request.getRecipientType()) ? 1 : 2);
        whisper.setTargetValue(request.getRecipientValue());
        whisper.setContent(request.getContent());
        whisper.setIsAnonymous(request.getIsAnonymous() ? 1 : 0);
        whisper.setStatus(1); // 正常状态
        
        if (request.getIsAnonymous()) {
            whisper.setSenderId(null);
            whisper.setSenderNickname(request.getSenderName() != null ? request.getSenderName() : "匿名用户");
        } else {
            if (currentUserId == null) {
                throw new BusinessException("发送实名悄悄话需要登录");
            }
            whisper.setSenderId(currentUserId);
            User sender = userRepository.findById(currentUserId)
                    .orElseThrow(() -> new ResourceNotFoundException("用户不存在"));
            whisper.setSenderNickname(sender.getUsername());
        }
        
        whisper = whisperRepository.save(whisper);
        
        return Result.success("悄悄话发送成功", convertToDTO(whisper));
    }
    
    /**
     * 获取我收到的悄悄话
     */
    @Operation(summary = "获取收到的悄悄话", description = "获取发送给我的悄悄话列表")
    @GetMapping("/received")
    public Result<PageResult<WhisperDTO>> getReceivedWhispers(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") int page,
            @Parameter(description = "每页数量") @RequestParam(defaultValue = "10") int size) {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            throw new BusinessException("用户未登录");
        }
        
        User currentUser = userRepository.findById(currentUserId)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在"));
        
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createTime").descending());
        Page<Whisper> whisperPage = whisperRepository.findWhispersToUser(currentUser.getUsername(), pageable);
        
        List<WhisperDTO> whisperDTOs = whisperPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return Result.success("获取成功", PageResult.of(whisperDTOs, whisperPage.getTotalElements(), page, size));
    }
    
    /**
     * 获取我发送的悄悄话
     */
    @Operation(summary = "获取发送的悄悄话", description = "获取我发送的悄悄话列表")
    @GetMapping("/sent")
    public Result<PageResult<WhisperDTO>> getSentWhispers(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") int page,
            @Parameter(description = "每页数量") @RequestParam(defaultValue = "10") int size) {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            throw new BusinessException("用户未登录");
        }
        
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createTime").descending());
        Page<Whisper> whisperPage = whisperRepository.findBySenderIdAndStatus(currentUserId, 1, pageable);
        
        List<WhisperDTO> whisperDTOs = whisperPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return Result.success("获取成功", PageResult.of(whisperDTOs, whisperPage.getTotalElements(), page, size));
    }
    
    /**
     * 通过暗号获取悄悄话
     */
    @Operation(summary = "通过暗号获取悄悄话", description = "获取发送给指定暗号的悄悄话")
    @GetMapping("/code/{code}")
    public Result<PageResult<WhisperDTO>> getWhispersByCode(
            @Parameter(description = "暗号") @PathVariable String code,
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") int page,
            @Parameter(description = "每页数量") @RequestParam(defaultValue = "10") int size) {
        
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createTime").descending());
        Page<Whisper> whisperPage = whisperRepository.findWhispersToSecretCode(code, pageable);
        
        List<WhisperDTO> whisperDTOs = whisperPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return Result.success("获取成功", PageResult.of(whisperDTOs, whisperPage.getTotalElements(), page, size));
    }
    
    /**
     * 获取悄悄话设置
     */
    @Operation(summary = "获取悄悄话设置", description = "获取当前用户的悄悄话设置")
    @GetMapping("/settings")
    public Result<WhisperSettingsDTO> getWhisperSettings() {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            throw new BusinessException("用户未登录");
        }
        
        WhisperSettings settings = whisperSettingsRepository.findByUserId(currentUserId)
                .orElse(createDefaultSettings(currentUserId));
        
        WhisperSettingsDTO dto = WhisperSettingsDTO.builder()
                .id(settings.getId())
                .allowAnonymous(settings.getAllowAnonymous() == 1)
                .enabled(true)
                .createdAt(settings.getCreateTime())
                .updatedAt(settings.getUpdateTime())
                .build();
        
        return Result.success("获取成功", dto);
    }
    
    /**
     * 更新悄悄话设置
     */
    @Operation(summary = "更新悄悄话设置", description = "更新当前用户的悄悄话设置")
    @PutMapping("/settings")
    @Transactional
    public Result<WhisperSettingsDTO> updateWhisperSettings(@Valid @RequestBody WhisperSettingsDTO request) {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            throw new BusinessException("用户未登录");
        }
        
        WhisperSettings settings = whisperSettingsRepository.findByUserId(currentUserId)
                .orElse(createDefaultSettings(currentUserId));
        
        settings.setAllowAnonymous(request.getAllowAnonymous() ? 1 : 0);
        settings.setNeedReview(0); // 暂时不支持审核
        settings.setMaxDailyCount(50); // 默认每日最大数量
        
        settings = whisperSettingsRepository.save(settings);
        
        WhisperSettingsDTO dto = WhisperSettingsDTO.builder()
                .id(settings.getId())
                .allowAnonymous(settings.getAllowAnonymous() == 1)
                .enabled(true)
                .createdAt(settings.getCreateTime())
                .updatedAt(settings.getUpdateTime())
                .build();
        
        return Result.success("更新成功", dto);
    }
    
    /**
     * 删除悄悄话
     */
    @Operation(summary = "删除悄悄话", description = "删除指定的悄悄话")
    @DeleteMapping("/{whisperId}")
    @Transactional
    public Result<Void> deleteWhisper(@Parameter(description = "悄悄话ID") @PathVariable Long whisperId) {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            throw new BusinessException("用户未登录");
        }
        
        Whisper whisper = whisperRepository.findById(whisperId)
                .orElseThrow(() -> new ResourceNotFoundException("悄悄话不存在"));
        
        if (whisper.getSenderId() == null || !whisper.getSenderId().equals(currentUserId)) {
            throw new BusinessException("只能删除自己发送的悄悄话");
        }
        
        whisper.setStatus(0); // 软删除
        whisperRepository.save(whisper);
        
        return Result.success("删除成功");
    }
    
    /**
     * 搜索悄悄话
     */
    @Operation(summary = "搜索悄悄话", description = "通过用户名或暗号搜索悄悄话")
    @GetMapping("/search")
    public Result<PageResult<WhisperDTO>> searchWhispers(
            @Parameter(description = "搜索关键词") @RequestParam String keyword,
            @Parameter(description = "搜索类型") @RequestParam(defaultValue = "all") String searchType,
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") int page,
            @Parameter(description = "每页数量") @RequestParam(defaultValue = "10") int size) {
        
        if (keyword == null || keyword.trim().isEmpty()) {
            throw new BusinessException("搜索关键词不能为空");
        }
        
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createTime").descending());
        Page<Whisper> whisperPage;
        
        switch (searchType.toLowerCase()) {
            case "username":
                // 精确搜索用户名
                whisperPage = whisperRepository.findWhispersToSpecificUser(keyword.trim(), pageable);
                break;
            case "code":
                // 精确搜索暗号
                whisperPage = whisperRepository.findWhispersToSpecificCode(keyword.trim(), pageable);
                break;
            case "all":
            default:
                // 模糊搜索用户名和暗号
                whisperPage = whisperRepository.searchWhispersByTargetValue(keyword.trim(), pageable);
                break;
        }
        
        List<WhisperDTO> whisperDTOs = whisperPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return Result.success("搜索成功", PageResult.of(whisperDTOs, whisperPage.getTotalElements(), page, size));
    }
    
    /**
     * 高级搜索悄悄话
     */
    @Operation(summary = "高级搜索悄悄话", description = "通过目标值和内容关键词搜索悄悄话")
    @GetMapping("/search/advanced")
    public Result<PageResult<WhisperDTO>> advancedSearchWhispers(
            @Parameter(description = "目标值关键词") @RequestParam(required = false) String targetKeyword,
            @Parameter(description = "内容关键词") @RequestParam(required = false) String contentKeyword,
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") int page,
            @Parameter(description = "每页数量") @RequestParam(defaultValue = "10") int size) {
        
        if ((targetKeyword == null || targetKeyword.trim().isEmpty()) && 
            (contentKeyword == null || contentKeyword.trim().isEmpty())) {
            throw new BusinessException("至少需要提供一个搜索关键词");
        }
        
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createTime").descending());
        Page<Whisper> whisperPage;
        
        if (targetKeyword != null && !targetKeyword.trim().isEmpty() && 
            contentKeyword != null && !contentKeyword.trim().isEmpty()) {
            // 组合搜索
            whisperPage = whisperRepository.searchWhispersByTargetAndContent(
                targetKeyword.trim(), contentKeyword.trim(), pageable);
        } else if (targetKeyword != null && !targetKeyword.trim().isEmpty()) {
            // 只搜索目标值
            whisperPage = whisperRepository.searchWhispersByTargetValue(targetKeyword.trim(), pageable);
        } else {
            // 只搜索内容
            whisperPage = whisperRepository.searchWhispers(contentKeyword.trim(), pageable);
        }
        
        List<WhisperDTO> whisperDTOs = whisperPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return Result.success("搜索成功", PageResult.of(whisperDTOs, whisperPage.getTotalElements(), page, size));
    }
    
    /**
     * 创建默认设置
     */
    private WhisperSettings createDefaultSettings(Long userId) {
        WhisperSettings settings = new WhisperSettings();
        settings.setUserId(userId);
        settings.setAllowAnonymous(1);
        settings.setNeedReview(0);
        settings.setMaxDailyCount(50);
        return whisperSettingsRepository.save(settings);
    }
    
    /**
     * 转换为DTO
     */
    private WhisperDTO convertToDTO(Whisper whisper) {
        WhisperDTO.WhisperDTOBuilder builder = WhisperDTO.builder()
                .id(whisper.getId())
                .content(whisper.getContent())
                .senderName(whisper.getSenderNickname())
                .recipientType(whisper.getTargetType() == 1 ? "username" : "code")
                .recipientValue(whisper.getTargetValue())
                .isAnonymous(whisper.getIsAnonymous() == 1)
                .isRead(false)
                .createdAt(whisper.getCreateTime());
        
        // 发送者信息（非匿名时）
        if (whisper.getSenderId() != null) {
            userRepository.findById(whisper.getSenderId()).ifPresent(sender -> {
                WhisperDTO.SenderInfo senderInfo = WhisperDTO.SenderInfo.builder()
                        .id(sender.getId())
                        .username(sender.getUsername())
                        .nickname(sender.getProfile() != null ? sender.getProfile().getNickname() : null)
                        .avatar(sender.getAvatar())
                        .build();
                builder.sender(senderInfo);
            });
        }
        
        return builder.build();
    }
} 